package md.mru.core.service;

import md.mru.core.common.BaseDtoMapper;
import md.mru.core.domains.*;
import md.mru.core.domains.orders.FolderOrder;
import md.mru.core.domains.type.OrderStateType;
import md.mru.core.dtos.*;
import md.mru.core.repositories.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author sergiu.marin
 * @since 16.04.2014.
 */
@Service
public class OrderService {

    @Value("${first_header_div}")
    private String firstHeaderDiv;
    @Value("${second_header_div}")
    private String secondHeaderDiv;
    @Autowired
    @Qualifier(value = "dtoMapper")
    private BaseDtoMapper mapper;
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private OrderTypeGroupRepository orderTypeGroupRepository;
    @Autowired
    private OrderTypeRepository orderTypeRepository;
    @Autowired
    private IssuerRepository issuerRepository;
    @Autowired
    private PublicFunctionRepository publicFunctionRepository;
    @Autowired
    private AdvancementRankRepository advancementRankRepository;
    @Autowired
    private EffectiveRepository effectiveRepository;
    @Autowired
    private OrderPatternRepository orderPatternRepository;

    public OrdersWrapper loadNextOrders(long folderId, int first, int size) {
        PageRequest request = new PageRequest(first, size, Sort.Direction.DESC, "createdDate");
        Page<FolderOrder> orders = orderRepository.loadFolderOrders(folderId, request);
        List<OrderDto> orderDtos = mapper.mapList(orders.getContent(), OrderDto.class);
        return new OrdersWrapper(orderDtos, orders.getTotalElements());
    }

    public long saveOrder(OrderDto orderDto) {
        FolderOrder order = mapper.map(orderDto, FolderOrder.class);
        return orderRepository.save(order).getId();
    }

    public List<OrderTypeGroupDto> loadOrderTypeGroups() {
        List<OrderTypeGroup> orderTypeGroups = orderTypeGroupRepository.findAll();
        return mapper.mapList(orderTypeGroups, OrderTypeGroupDto.class);
    }

    public List<OrderTypeGroupDto> loadOrderTypeGroups(long folderStateId) {
        List<OrderTypeGroup> orderTypeGroups = orderTypeGroupRepository.loadOrderTypeGroups(folderStateId).getOrderTypeGroups();
        return mapper.mapList(orderTypeGroups, OrderTypeGroupDto.class);
    }

    public List<OrderTypeDto> loadOrderTypesByGroup(long groupId) {
        List<OrderType> orderTypes = orderTypeRepository.loadOrderTypeByGroup(groupId);
        return mapper.mapList(orderTypes, OrderTypeDto.class);
    }

    public OrderTypeDto loadOrderType(long typeId) {
        OrderType orderType = orderTypeRepository.loadOrderType(typeId);
        return mapper.map(orderType, OrderTypeDto.class);
    }

    public List<OrderTypeDto> loadOrderTypesByGroups(List<OrderTypeGroupDto> orderTypeGroups) {
        Set<Long> ids = new HashSet<>();
        for (OrderTypeGroupDto tg : orderTypeGroups) {
            ids.add(tg.getId());
        }
        List<OrderType> orderTypes = orderTypeRepository.loadOrderTypesByGroups(ids);
        return mapper.mapList(orderTypes, OrderTypeDto.class);
    }

    public List<IssuerDto> loadActiveIssuers() {
        List<Issuer> issuers = issuerRepository.loadActiveIssuers();
        return mapper.mapList(issuers, IssuerDto.class);
    }

    public List<PublicFunctionDto> getPublicFunctions() {
        List<PublicFunction> publicFunctions = publicFunctionRepository.findAll();
        return mapper.mapList(publicFunctions, PublicFunctionDto.class);
    }

    public List<AdvancementRankDto> getAdvancementRanks() {
        List<AdvancementRank> advancementRanks = advancementRankRepository.findAll();
        return mapper.mapList(advancementRanks, AdvancementRankDto.class);
    }

    public List<EffectiveDto> getEffectives() {
        List<Effective> effectives = effectiveRepository.findAll();
        return mapper.mapList(effectives, EffectiveDto.class);
    }

    public List<OrderDto> loadOrderWithExpiredFolderStates(Set<Long> folderStateIds) {
        List<FolderOrder> orders = orderRepository.loadOrderWithExpiredFolderStates(folderStateIds);
        return mapper.mapList(orders, OrderDto.class);
    }

    public Date getFolderEmployedDate(long folderId) {
        List<Long> orderTypeGroupIds = new ArrayList<>(Arrays.asList(new Long[]{OrderStateType.EMPLOYMENT.id, OrderStateType.TRANSFER.id}));
        return orderRepository.getFolderEmployedDate(folderId, orderTypeGroupIds);
    }

    @Transactional
    public void saveOrderPattern(OrderPatternDto orderPatternDto) {
        OrderPattern orderPattern = mapper.map(orderPatternDto, OrderPattern.class);
        orderPatternRepository.save(orderPattern);
    }

    @Transactional
    public void deleteOrderPattern(long orderPatternId) {
        orderPatternRepository.deleteOrderPattern(orderPatternId);
    }

    public String getOrderTemplateHeader() {
        return firstHeaderDiv + secondHeaderDiv;
    }

}
